package com.ly.cloud.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import com.ly.cloud.dto.XnDto;
import com.ly.cloud.dto.XnxqDto;
import com.ly.cloud.dto.XqDto;
import com.ly.cloud.entity.XnPo;
import com.ly.cloud.entity.XnxqPo;
import com.ly.cloud.entity.XnxqRlbPo;
import com.ly.cloud.entity.XqPo;
import com.ly.cloud.exception.CloudException;
import com.ly.cloud.exception.biz.BusinessException;
import com.ly.cloud.exception.mapper.DBException;
import com.ly.cloud.mapper.XnMapper;
import com.ly.cloud.mapper.XnxqMapper;
import com.ly.cloud.mapper.XnxqRlbMapper;
import com.ly.cloud.mapper.XqMapper;
import com.ly.cloud.service.SemesterService;
import com.ly.cloud.utils.BeanCopyUtils;
import com.ly.cloud.utils.CCalendar;
import com.ly.cloud.utils.DatetimeUtils;
import com.ly.cloud.vo.XnVo;
import com.ly.cloud.vo.XnxqVo;
import com.ly.cloud.vo.XqVo;

/**
 * 学年学期ServiceImpl
 * 该impl包括学年设置、学期设置、学年学期设置
 * @author caihuihai
 * @date 2018年12月11日 下午3:07:38
 */
@Service
@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
public class SemesterServiceImpl extends ServiceImpl<XnMapper,XnPo> implements SemesterService {
	
	@Autowired
	private XnMapper xnMapper;
	@Autowired
	private XqMapper xqMapper;
	@Autowired
	private XnxqMapper xnxqMapper; //学年学期mapper
	@Autowired
	private XnxqRlbMapper xnxqRlbMapper;  //校历mapper
	
	/**
	 * 查询学年列表
	 * @param xnmc
	 * @return
	 */
	@Override
	public List<XnVo> queryList(String xnmc) {
		try {
			//调用BaseMapper中的带参数查询
			EntityWrapper<XnPo> ew = new EntityWrapper<>();
	        ew.like(!Strings.isNullOrEmpty(xnmc), "xnmc", "%" + xnmc + "%");
	        //按开始年份降序排
	        ew.orderBy("ksnf", false);  
	        List<XnPo> poList = xnMapper.selectList(ew);
	        //把dto对象转换成vo对象
			return BeanCopyUtils.copyListProperties(poList, XnVo.class);
		} catch (Exception e) {
			throw new CloudException("查询异常，请重试!", e);
		}
	}

	/**
	 * 新增学年
	 */
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED) //具有多次数据库操作，需要加上事务
	@Override
	public boolean insert(XnDto dto,String loginUserName) {
		try {
			XnPo po = new XnPo();
			BeanUtils.copyProperties(dto, po);
			po.setCjr(loginUserName);
			po.setCjsj(new Date());
			/*新增学年，如果是启用的话，需要把所有的学年先设置为不启用
			 * 20181212改为只设置启用不启用
			if(!Strings.isNullOrEmpty(dto.getSfyx()) && "1".equals(dto.getSfyx())) {
				updateAllXn();
			}*/
			return xnMapper.insert(po)>0?true:false;
		} catch (Exception e) {
			throw new DBException("新增学年失败！", e);
		}
	}
	
	/**
	 * 更新所有的学年为不启用
	 */
	private void updateAllXn() {
		try {
			XnPo po = new XnPo();
			po.setSfyx("0");
			xnMapper.update(po, null);
		} catch (Exception e) {
			throw new DBException("更新所有学年数据失败！", e);
		}
	}
	
	/**
	 * 根据学年主键查询学年信息
	 */
	@Override
	public XnVo findXnByZj(String xnzj) {
		try {
			XnVo vo = new XnVo();
			XnPo po = new XnPo();
			po.setXnzj(xnzj);
			XnPo selPo = xnMapper.selectOne(po);
			BeanUtils.copyProperties(selPo, vo);
			return vo;
		} catch (Exception e) {
			throw new DBException("查询学年数据失败！", e);
		}
	}

	/**
	 * 修改学年
	 */
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED) //具有多次数据库操作，需要加上事务
	@Override
	public boolean updateById(XnDto dto,String loginUserName) {
		try {
			XnPo po = new XnPo();
			BeanUtils.copyProperties(dto, po);
			po.setXgr(loginUserName);
			po.setXgsj(new Date());
			/*修改学年，如果是启用的话，需要把所有的学年先设置为不启用
			 * 20181212改为只启用不启用
			if(!Strings.isNullOrEmpty(dto.getSfyx()) && "1".equals(dto.getSfyx())) {
				updateAllXn();
			}*/
			EntityWrapper<XnPo> ew = new EntityWrapper<>();
			ew.where("xnzj={0}", po.getXnzj());
			return retBool(xnMapper.update(po, ew));
		} catch (Exception e) {
			throw new BusinessException("修改学年失败！", e);
		}
	}

	/**
	 * 删除学年
	 */
	@Override
	public boolean delete(String xnzj) {
		try {
			EntityWrapper<XnPo> ew = new EntityWrapper<>();
			ew.where("xnzj={0}", xnzj);
			return xnMapper.delete(ew)>0?true:false;
		} catch (Exception e) {
			throw new DBException("删除学年失败！", e);
		}
	}

	/**
	 * 查询学期列表
	 */
	@Override
	public List<XqVo> queryXqList() {
		try {
			//调用BaseMapper中的带参数查询
			EntityWrapper<XqPo> ew = new EntityWrapper<>();
	        //按学期代码升序排，学期名称升序排
	        ew.orderBy("xqdm", true).orderBy("xqmc", true);
	        List<XqPo> poList = xqMapper.selectList(ew);
	        //把dto对象转换成vo对象
			return BeanCopyUtils.copyListProperties(poList, XqVo.class);
		} catch (Exception e) {
			throw new CloudException("查询异常，请重试!", e);
		}
	}

	/**
	 * 新增学期
	 */
	@Override
	public boolean insertXq(XqDto dto,String loginUserName) {
		try {
			XqPo po = new XqPo();
			BeanUtils.copyProperties(dto, po);
			po.setCjr(loginUserName);
			po.setCjsj(new Date());
			return xqMapper.insert(po)>0?true:false;
		} catch (Exception e) {
			throw new DBException("新增学期失败！", e);
		}
	}
	
	/**
	 * 根据学期主键查询学期信息
	 */
	@Override
	public XqVo findXqByZj(String xqdm) {
		try {
			XqVo vo = new XqVo();
			XqPo po = new XqPo();
			po.setXqdm(xqdm);
			XqPo selPo = xqMapper.selectOne(po);
			BeanUtils.copyProperties(selPo, vo);
			return vo;
		} catch (Exception e) {
			throw new DBException("查询学期数据失败！", e);
		}
	}

	/**
	 * 修改学期
	 */
	@Override
	public boolean updateXq(XqDto dto,String loginUserName) {
		try {
			XqPo po = new XqPo();
			BeanUtils.copyProperties(dto, po);
			po.setXgr(loginUserName);
			po.setXgsj(new Date());
			EntityWrapper<XqPo> ew = new EntityWrapper<>();
			ew.where("xqdm={0}", po.getXqdm());
			return retBool(xqMapper.update(po, ew));
		} catch (Exception e) {
			throw new BusinessException("修改学期失败！", e);
		}
	}

	/**
	 * 删除学期
	 */
	@Override
	public boolean deleteXq(String xqdm) {
		try {
			EntityWrapper<XqPo> ew = new EntityWrapper<>();
			ew.where("xqdm={0}", xqdm);
			return xqMapper.delete(ew)>0?true:false;
		} catch (Exception e) {
			throw new DBException("删除学期失败！", e);
		}
	}

	/**
	 * 获取学年学期列表
	 */
	@Override
	public List<XnxqVo> queryXnXqList(String xndm, String xqdm, String sfdqxq) {
		try {
	        List<XnxqVo> poList = xnxqMapper.selectXnxqList(xndm, xqdm, sfdqxq);
	        //把dto对象转换成vo对象
			return poList;
		} catch (Exception e) {
			throw new CloudException("查询异常，请重试!", e);
		}
	}

	/**
	 * 获取有效学年list
	 */
	@Override
	public List<XnVo> getXnList() {
		try {
			//只查询有效学年,按开始年份降序排
			EntityWrapper<XnPo> ew = new EntityWrapper<>();
			ew.where("sfyx={0}", "1").orderBy("ksnf", false);
			List<XnPo> poList = xnMapper.selectList(ew);
	        //把dto对象转换成vo对象
			return BeanCopyUtils.copyListProperties(poList, XnVo.class);
		} catch (Exception e) {
			throw new CloudException("查询异常，请重试!", e);
		}
	}

	/**
	 * 获取有效学期list
	 */
	@Override
	public List<XqVo> getXqList() {
		try {
			//只查询启用学期,按学期代码升序排
			EntityWrapper<XqPo> ew = new EntityWrapper<>();
			ew.where("sfqy={0}", "1").orderBy("xqdm", true);
			List<XqPo> poList = xqMapper.selectList(ew);
	        //把dto对象转换成vo对象
			return BeanCopyUtils.copyListProperties(poList, XqVo.class);
		} catch (Exception e) {
			throw new CloudException("查询异常，请重试!", e);
		}
	}
	
	/**
	 * 根据学年主键和学期代码查询学年学期信息
	 */
	@Override
	public XnxqVo findXnXqByZj(String xndm,String xqdm) {
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			XnxqVo vo = new XnxqVo();
			XnxqPo po = new XnxqPo();
			po.setXndm(xndm);
			po.setXqdm(xqdm);
			XnxqPo selPo = xnxqMapper.selectOne(po);
			BeanUtils.copyProperties(selPo, vo);
			if(selPo.getKsrq() != null) {
				vo.setKsrq(sdf.format(selPo.getKsrq()));
			}
			if(selPo.getJsrq() != null) {
				vo.setJsrq(sdf.format(selPo.getJsrq()));
			}
			return vo;
		} catch (Exception e) {
			throw new DBException("查询学年学期数据失败！", e);
		}
	}

	/**
	 * 新增或修改学年学期，生成校历
	 */
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED) //具有多次数据库操作，需要加上事务
	@Override
	public boolean submitXnXq(XnxqDto dto) {
		try {
			int tag = 0;
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			XnxqPo po = new XnxqPo();
			BeanUtils.copyProperties(dto, po);
			po.setKsrq(sdf.parse(dto.getKsrq()));
			po.setJsrq(sdf.parse(dto.getJsrq()));
			//如果是当前学期的话，则当前xx值设为1；如果不是当前学期，则默认传什么保存什么值
			if(!Strings.isNullOrEmpty(dto.getSfdqxq()) && "1".equals(dto.getSfdqxq())) {
				po.setSfdqxkxq("1");  //选课学期
				po.setSfkks("1");  //考试学期
				po.setSfkkxq("1");  //开课学期
				po.setSfkpk("1");  //排课学期
				po.setSfzcxq("1");  //注册学期
				//并且把所有数据的当前学期设置为0
				updateAllXq();
			} 
			if("add".equals(dto.getType())) {  //新增
				tag = xnxqMapper.insert(po);
			} else {
				EntityWrapper<XnxqPo> ew = new EntityWrapper<>();
				ew.where("xndm={0} and xqdm={1}", po.getXndm(),po.getXqdm());
				tag = xnxqMapper.update(po, ew);
			}
			//生成校历
			if(!Strings.isNullOrEmpty(dto.getSfscxl()) && "1".equals(dto.getSfscxl())) {
				insertRl(dto.getKsrq(),dto.getJsrq(),dto.getXndm(),dto.getXqdm());
			}
			return tag>0?true:false;
		} catch (Exception e) {
			throw new CloudException("操作异常，请重试!", e);
		}
	}
	
	/**
	 * 更新所有的当前学期为0
	 */
    private void updateAllXq() {
    	try {
			XnxqPo po = new XnxqPo();
			po.setSfdqxq("0");
			xnxqMapper.update(po, null);
		} catch (Exception e) {
			throw new DBException("更新所有学期数据失败！", e);
		}
	}

	/**
     * 生成校历，先根据开始日期和结束日期删除旧的，再新生成
     * @param ksrq
     * @param jsrq
     * @param xndm
     * @param xqdm
     * @throws Exception
     */
    private void insertRl(String ksrq, String jsrq, String xndm,
                          String xqdm) throws Exception {
    	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    	SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMdd");
    	//先删除旧数据
    	EntityWrapper<XnxqRlbPo> ew = new EntityWrapper<>();
    	ew.between("xlrq", ksrq, jsrq);
    	xnxqRlbMapper.delete(ew);
        //新增数据
        Date sDate = sdf.parse(ksrq);  //开始日期
        Date eDate = sdf.parse(jsrq);  //结束日期
        List<Date> list = DatetimeUtils.getAllDatesBetweeStoE(sDate, eDate); //获取总天数
        int zs = 1; // 周数,从第一周开始,每周第一天是星期天
        for (int i = 0; i < list.size(); i++) {
            Date date = list.get(i);
            int xqj = DatetimeUtils.isXqjofDate(date);  //星期几
            String sdate = sdf.format(date);
            String zjStr = sdf2.format(date);
            zjStr = xndm + xqdm + zjStr;
            Long zj = Long.parseLong(zjStr);
            String[] strs = sdate.toString().split("-");
            String nlrq = CCalendar.getLunar(strs[0], strs[1], strs[2]);
            if (nlrq != null) {
                String[] nstrs = nlrq.split("-");
                if (nstrs != null && nstrs.length > 0) {
                	XnxqRlbPo rlbPo = new XnxqRlbPo();
                	rlbPo.setZj(zj);  //主键
                	rlbPo.setXndm(xndm);
                    rlbPo.setXqdm(xqdm);
                    rlbPo.setXlrq(sdate);  //新历日期
                    rlbPo.setNlrq(nlrq);   //农历日期
                    rlbPo.setXln(strs[0]);  //新历年
                    rlbPo.setXly(strs[1]);  //新历月
                    rlbPo.setXlr(strs[2]);  //新历日
                    rlbPo.setNln(nstrs[0]);  //农历年
                    rlbPo.setNly(nstrs[1]);  //农历月
                    rlbPo.setNlr(nstrs[2]);  //农历日
                    rlbPo.setXqz(zs);       //学期周次
                    rlbPo.setXqj(xqj+"");  //星期几
                    xnxqRlbMapper.insert(rlbPo);
                }
            }
            if (xqj == 6) { //表示星期六
                zs++;
            }
        }
    }

    /**
     * 删除学年学期
     */
	@Override
	public boolean deleteXnXq(String xndm, String xqdm) {
		try {
			EntityWrapper<XnxqPo> ew = new EntityWrapper<>();
			ew.where("xndm={0} and xqdm={1}", xndm,xqdm);
			return retBool(xnxqMapper.delete(ew));
		} catch (Exception e) {
			throw new DBException("删除学年学期失败！", e);
		}
	}

	/**
	 * 查询学年学期的列表(通用)
	 * @return List<String> 
	 * @author luhuacong
	 * @date 2018/12/27
	 */
	@Override
	public List<String> selectXnXqListTy() {
		List<String> list = new ArrayList<String>();
		try {
			list = xnxqMapper.selectXnXqListTy();
		} catch (Exception e) {
			throw new CloudException("查询学年学期失败",e);
		}
	
		return list;
	}


}
